import { createWorker, type Worker } from 'tesseract.js'
import type { OCRResult } from '@/types/screenshot'

/**
 * OCR 服务类
 */
class OCRService {
  private worker: Worker | null = null
  private isInitialized: boolean = false
  private isInitializing: boolean = false

  /**
   * 初始化 OCR Worker
   */
  async initialize(lang: string = 'chi_sim+eng'): Promise<void> {
    if (this.isInitialized) return
    if (this.isInitializing) {
      // 等待初始化完成
      while (this.isInitializing) {
        await new Promise(resolve => setTimeout(resolve, 100))
      }
      return
    }

    this.isInitializing = true

    try {
      console.log('正在初始化 OCR Worker，语言:', lang)
      
      this.worker = await createWorker(lang, 1, {
        logger: (m) => {
          if (m.status === 'loading language traineddata') {
            console.log('OCR: 正在下载语言包...', m.progress ? Math.round(m.progress * 100) + '%' : '')
          } else if (m.status === 'initializing api') {
            console.log('OCR: 正在初始化 API...')
          } else if (m.status === 'initialized api') {
            console.log('OCR: API 初始化完成')
          } else if (m.status === 'recognizing text') {
            console.log('OCR: 正在识别文字...', m.progress ? Math.round(m.progress * 100) + '%' : '')
          } else {
            console.log('OCR:', m.status, m.progress ? Math.round(m.progress * 100) + '%' : '')
          }
        }
      })
      
      console.log('OCR Worker 初始化成功')
      this.isInitialized = true
    } catch (error) {
      console.error('OCR 初始化失败:', error)
      this.isInitializing = false
      throw new Error(`OCR 初始化失败: ${error instanceof Error ? error.message : String(error)}`)
    } finally {
      this.isInitializing = false
    }
  }

  /**
   * 识别图片中的文字
   */
  async recognize(
    imageDataUrl: string, 
    progressCallback?: (progress: { status: string; progress: number }) => void
  ): Promise<OCRResult> {
    try {
      if (!this.isInitialized) {
        console.log('OCR Worker 未初始化，开始初始化...')
        if (progressCallback) {
          progressCallback({ status: '正在初始化 OCR...', progress: 0 })
        }
        await this.initialize()
        if (progressCallback) {
          progressCallback({ status: '初始化完成', progress: 0.5 })
        }
      }

      if (!this.worker) {
        throw new Error('OCR Worker 未初始化')
      }

      console.log('开始识别文字...')
      if (progressCallback) {
        progressCallback({ status: '正在识别文字...', progress: 0.6 })
      }

      const result = await this.worker.recognize(imageDataUrl)
      console.log('识别完成，文本长度:', result.data.text.length)
      
      if (progressCallback) {
        progressCallback({ status: '识别完成', progress: 1 })
      }

      return {
        text: result.data.text,
        confidence: result.data.confidence,
        words: (result.data.words || []).map(word => ({
          text: word.text,
          confidence: word.confidence,
          bbox: {
            x0: word.bbox.x0,
            y0: word.bbox.y0,
            x1: word.bbox.x1,
            y1: word.bbox.y1,
          }
        }))
      }
    } catch (error) {
      console.error('OCR 识别失败:', error)
      throw new Error(`OCR 识别失败: ${error instanceof Error ? error.message : String(error)}`)
    }
  }
  
  /**
   * 检查是否已初始化
   */
  isReady(): boolean {
    return this.isInitialized
  }
  
  /**
   * 预加载/初始化 OCR（可在应用启动时调用）
   */
  async preload(): Promise<void> {
    if (!this.isInitialized && !this.isInitializing) {
      console.log('预加载 OCR...')
      await this.initialize()
    }
  }

  /**
   * 识别图片区域中的文字
   */
  async recognizeArea(
    imageDataUrl: string,
    x: number,
    y: number,
    width: number,
    height: number
  ): Promise<OCRResult> {
    // 先裁剪图片区域
    const canvas = document.createElement('canvas')
    canvas.width = width
    canvas.height = height
    const ctx = canvas.getContext('2d')

    if (!ctx) {
      throw new Error('无法获取 Canvas 上下文')
    }

    const img = new Image()
    await new Promise((resolve, reject) => {
      img.onload = resolve
      img.onerror = reject
      img.src = imageDataUrl
    })

    ctx.drawImage(img, x, y, width, height, 0, 0, width, height)
    const croppedDataUrl = canvas.toDataURL('image/png')

    return this.recognize(croppedDataUrl)
  }

  /**
   * 销毁 Worker
   */
  async terminate(): Promise<void> {
    if (this.worker) {
      await this.worker.terminate()
      this.worker = null
      this.isInitialized = false
    }
  }
}

// 导出单例
export const ocrService = new OCRService()

